using System;
using Firestarter.Test.Base;
using FireStarterModeller.BO;
using Habanero.Base;
using Habanero.BO;
using Habanero.BO.ClassDefinition;
using NUnit.Framework;

namespace FireStarterModeller.Test.BO
{
    [TestFixture]
    public class TestInheritanceHierachyDiscriminatorsAreEqual
    {
        [SetUp]
        public void SetupTest()
        {
            //Runs every time that any testmethod is executed
            TestUtilsDomain.SetupTest();
            BORegistry.DataAccessor = new DataAccessorInMemory();
        }

        [TestFixtureSetUp]
        public void TestFixtureSetup()
        {
            //Code that is executed before any test is run in this class. If multiple tests
            // are executed then it will still only be called once.
            TestUtilsDomain.SetupFixture();
        }

        [TearDown]
        public void TearDownTest()
        {
            //runs every time any testmethod is complete
        }

        #region TestInheritanceHierachyDiscriminatorsAreEqual

        [Test]
        public void Test_Constructor()
        {
            //---------------Set up test pack-------------------
            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------
            IBusinessObjectRule rule = new DMInheritanceHierachyDiscriminatorsAreEqual();
            //---------------Test Result -----------------------
            Assert.IsNotNull(rule);
            Assert.AreEqual("DMInheritanceHierachyDiscriminatorsAreEqual", rule.Name);
            Assert.AreEqual(ErrorLevel.Warning, rule.ErrorLevel);
        }

//        [Test]
//        public void Test_Constructor_WhenInheritanceRelationshipNull_ShouldRaiseError()
//        {
//            //---------------Set up test pack-------------------
//            //---------------Assert Precondition----------------
//            //---------------Execute Test ----------------------
//            try
//            {
//                new DMInheritanceHierachyDiscriminatorsAreEqual(null);
//                Assert.Fail("expected ArgumentNullException");
//            }
//                //---------------Test Result -----------------------
//            catch (ArgumentNullException ex)
//            {
//                StringAssert.Contains("Value cannot be null", ex.Message);
//                StringAssert.Contains("inheritanceRelationship", ex.ParamName);
//            }
//        }  

        [Test]
        public void Test_WhenDiscriminatorNotIdenticalForEntireHierachy_ShouldFail()
        {
            //---------------Set up test pack-------------------
            DMProperty parentDiscriminatorProp = TestUtilsShared.CreateSavedDMProperty();
            TestUtilsDMProperty.SetDMPropIntType(parentDiscriminatorProp);
            parentDiscriminatorProp.Save();

            DMInheritanceRelationship childParentRelationship = new DMInheritanceRelationship();
            IDMClass parentClass = parentDiscriminatorProp.Class;
            DMClass childClass = TestUtilsShared.CreateSavedDMClass(parentClass.Assembly);
            DMProperty childDiscriminatorProp = TestUtilsDMProperty.CreateUnsavedValidDMProperty(childClass);
            childParentRelationship.SubClass = childClass;
            childParentRelationship.SuperClass = (DMClass) parentClass;
            childParentRelationship.Discriminator = parentDiscriminatorProp.PropertyName;
            childClass.Save();
            childParentRelationship.Save();

            DMClass grandChildClass = TestUtilsShared.CreateSavedDMClass(parentClass.Assembly);
            DMInheritanceRelationship grandChildInheritanceRelationship = new DMInheritanceRelationship();
            grandChildInheritanceRelationship.SubClass = grandChildClass;
            grandChildInheritanceRelationship.SuperClass = childClass;
            grandChildInheritanceRelationship.Discriminator = childDiscriminatorProp.PropertyName;
            grandChildClass.Save();
            grandChildInheritanceRelationship.Save();

            IBusinessObjectRule rule = new DMInheritanceHierachyDiscriminatorsAreEqual();
            //---------------Assert Precondition----------------
            Assert.AreNotEqual(grandChildInheritanceRelationship.Discriminator, childParentRelationship.Discriminator);
            //---------------Execute Test ----------------------
            bool isValid = rule.IsValid(grandChildInheritanceRelationship);
            //---------------Test Result -----------------------
            Assert.IsFalse(isValid);
            StringAssert.Contains("The discriminator for the superclass of '", rule.Message);
            StringAssert.Contains("'" + grandChildClass.ToString() + "'", rule.Message);
            StringAssert.Contains("' must be the same property as the superclass's superclass", rule.Message);
        }

        [Test]
        public void Test_WhenDiscriminatorIdenticalForEntireHierachy_ShouldPass()
        {
            //---------------Set up test pack-------------------
            DMProperty parentDiscriminatorProp = TestUtilsShared.CreateSavedDMProperty();
            TestUtilsDMProperty.SetDMPropIntType(parentDiscriminatorProp);
            parentDiscriminatorProp.Save();

            DMInheritanceRelationship childParentRelationship = new DMInheritanceRelationship();
            IDMClass parentClass = parentDiscriminatorProp.Class;
            DMClass childClass = TestUtilsShared.CreateSavedDMClass(parentClass.Assembly);
            childParentRelationship.SubClass = childClass;
            childParentRelationship.SuperClass = (DMClass) parentClass;
            childParentRelationship.Discriminator = parentDiscriminatorProp.PropertyName;
            childClass.Save();
            childParentRelationship.Save();

            DMClass grandChildClass = TestUtilsShared.CreateSavedDMClass(parentClass.Assembly);
            DMInheritanceRelationship grandChildInheritanceRelationship = new DMInheritanceRelationship
                      {
                          SubClass = grandChildClass,
                          SuperClass = childClass
                      };
            grandChildInheritanceRelationship.Discriminator = parentDiscriminatorProp.PropertyName;
            grandChildClass.Save();
            grandChildInheritanceRelationship.Save();

            IBusinessObjectRule rule = new DMInheritanceHierachyDiscriminatorsAreEqual();
            //---------------Assert Precondition----------------
            Assert.AreEqual(grandChildInheritanceRelationship.Discriminator, childParentRelationship.Discriminator);
            //---------------Execute Test ----------------------
            bool isValid = rule.IsValid(grandChildInheritanceRelationship);
            //---------------Test Result -----------------------
            Assert.IsTrue(isValid);
        }

        [Test]
        public void Test_WhenNoGrandChild_ShouldPass()
        {
            //---------------Set up test pack-------------------
            DMProperty parentDiscriminatorProp = TestUtilsShared.CreateSavedDMProperty();
            TestUtilsDMProperty.SetDMPropIntType(parentDiscriminatorProp);
            parentDiscriminatorProp.Save();

            DMInheritanceRelationship childParentRelationship = new DMInheritanceRelationship();
            IDMClass parentClass = parentDiscriminatorProp.Class;
            DMClass childClass = TestUtilsShared.CreateSavedDMClass(parentClass.Assembly);
            childParentRelationship.SubClass = childClass;
            childParentRelationship.SuperClass = (DMClass) parentClass;
            childParentRelationship.Discriminator = parentDiscriminatorProp.PropertyName;
            childClass.Save();
            childParentRelationship.Save();
            IBusinessObjectRule rule = new DMInheritanceHierachyDiscriminatorsAreEqual();
            //---------------Assert Precondition----------------
            Assert.AreEqual(ORMapping.SingleTableInheritance, childParentRelationship.InheritanceType);
            //---------------Execute Test ----------------------
            bool isValid = rule.IsValid(childParentRelationship);
            //---------------Test Result -----------------------
            Assert.IsTrue(isValid);
        }

        [Test]
        public void Test_WhenNoGrandChildAndConcrete_ShouldPass()
        {
            //---------------Set up test pack-------------------
            DMProperty parentDiscriminatorProp = TestUtilsShared.CreateSavedDMProperty();
            TestUtilsDMProperty.SetDMPropIntType(parentDiscriminatorProp);
            parentDiscriminatorProp.Save();

            DMInheritanceRelationship childParentRelationship = new DMInheritanceRelationship();
            IDMClass parentClass = parentDiscriminatorProp.Class;
            DMClass childClass = TestUtilsShared.CreateSavedDMClass(parentClass.Assembly);
            childParentRelationship.SubClass = childClass;
            childParentRelationship.SuperClass = (DMClass) parentClass;
            childParentRelationship.Discriminator = parentDiscriminatorProp.PropertyName;
            childParentRelationship.InheritanceType = ORMapping.ConcreteTableInheritance;
            childClass.Save();
            childParentRelationship.Save();
            IBusinessObjectRule rule = new DMInheritanceHierachyDiscriminatorsAreEqual();
            //---------------Assert Precondition----------------
            Assert.AreEqual(ORMapping.ConcreteTableInheritance, childParentRelationship.InheritanceType);
            //---------------Execute Test ----------------------
            bool isValid = rule.IsValid(childParentRelationship);
            //---------------Test Result -----------------------
            Assert.IsTrue(isValid);
        }

        [Test]
        public void Test_WhenGrandParentConcreteTable_ShouldReturnTrue()
        {
            //---------------Set up test pack-------------------
            DMProperty parentDiscriminatorProp = TestUtilsShared.CreateSavedDMProperty();
            TestUtilsDMProperty.SetDMPropIntType(parentDiscriminatorProp);
            parentDiscriminatorProp.Save();

            DMInheritanceRelationship childParentRelationship = new DMInheritanceRelationship();
            IDMClass parentClass = parentDiscriminatorProp.Class;
            DMClass childClass = TestUtilsShared.CreateSavedDMClass(parentClass.Assembly);
            DMProperty childDiscriminatorProp = TestUtilsDMProperty.CreateUnsavedValidDMProperty(childClass);
            childParentRelationship.SubClass = childClass;
            childParentRelationship.SuperClass = (DMClass) parentClass;
            childParentRelationship.Discriminator = parentDiscriminatorProp.PropertyName;
            childParentRelationship.InheritanceType = ORMapping.ConcreteTableInheritance;
            childClass.Save();
            childParentRelationship.Save();

            DMClass grandChildClass = TestUtilsShared.CreateSavedDMClass(parentClass.Assembly);
            DMInheritanceRelationship grandChildInheritanceRelationship = new DMInheritanceRelationship();
            grandChildInheritanceRelationship.SubClass = grandChildClass;
            grandChildInheritanceRelationship.SuperClass = childClass;
            grandChildInheritanceRelationship.Discriminator = childDiscriminatorProp.PropertyName;
            grandChildClass.Save();
            grandChildInheritanceRelationship.Save();

            IBusinessObjectRule rule = new DMInheritanceHierachyDiscriminatorsAreEqual();
            //---------------Assert Precondition----------------
            Assert.AreEqual(ORMapping.ConcreteTableInheritance, childParentRelationship.InheritanceType);
            Assert.AreNotEqual(childParentRelationship.Discriminator, grandChildInheritanceRelationship.Discriminator);
            //---------------Execute Test ----------------------
            bool isValid = rule.IsValid(grandChildInheritanceRelationship);
            //---------------Test Result -----------------------
            Assert.IsTrue(isValid);
        }
        #endregion
    }
}